package org.ch02.hw.demo11;

import java.lang.reflect.Field;

/**
 * @author ZJL
 * @date 2025-03-19
 */
public class BeanUtil {

    /**
     * 1、设置何意对象的属性值
     *
     * @param bean         Bean 对象
     * @param propertyName 字段名称
     * @param value        设置字段的值
     */
    public static void setProperty(Object bean, String propertyName, Object value) {
        // 获取到bean 对象
        Class<?> clazz = bean.getClass();
        try {
            // 获取要设置的属性
            Field declaredField = clazz.getDeclaredField(propertyName);
            // 开放权限
            declaredField.setAccessible(true);
            // 给拿到的属性设置值
            declaredField.set(bean, value);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException("未知字段", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("初始化属性失败", e);
        }
    }

    /**
     * 2、获取任意对象的属性值
     *
     * @param bean         Bean 对象
     * @param propertyName 字段名称
     * @return
     */
    public static Object getProperty(Object bean, String propertyName) {
        // 获取到bean 对象
        Class<?> clazz = bean.getClass();
        try {
            // 获取要拿到的属性
            Field declaredField = clazz.getDeclaredField(propertyName);
            declaredField.setAccessible(true);
            return declaredField.get(bean);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException("未知的字段", e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException("获取字段失败", e);
        }
    }

    /**
     * 3、复制某个对象的属性值到另一个对象中
     *
     * @param sourceBean 源 Bean 对象
     * @param targetBean 目标 Bean 对象
     */
    public static void copyProperties(Object sourceBean, Object targetBean) {
        // 获取源对象的class对象
        Class<?> sourceBeanClass = sourceBean.getClass();
        // 获取目标对象的class对象
        Class<?> targetBeanClass = targetBean.getClass();
        if (sourceBeanClass != targetBeanClass) {
            throw new RuntimeException("不是同一个类对象，无法复制！！！");
        }
        // 获取到源对象的所有字段
        Field[] sourceFields = sourceBeanClass.getDeclaredFields();
        // 获取到目标对象的所有字段
        Field[] targetFields = targetBeanClass.getDeclaredFields();
        //遍历源对象的的所有字段
        for (Field sourceField : sourceFields) {
            try {
                // 3.获取源 Bean 对象的某个字段数据
                sourceField.setAccessible(true);
                Object sourceFieldData = sourceField.get(sourceBean);

                // 4.获取源 Bean 对象的某个字段的名称
                // 注意：这里是基于源对象的字段名称，获取目标对象的字段对象
                String sourceFieldName = sourceField.getName();

                // 5.获取目标 Bean 对象对应的 Filed 对象
                Field targetField = targetBeanClass.getDeclaredField(sourceFieldName);

                // 6.开放权限
                targetField.setAccessible(true);

                // 7.拷贝赋值
                targetField.set(targetBean, sourceFieldData);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            } catch (NoSuchFieldException e) {
                throw new RuntimeException("未知字段", e);
            }
        }
    }

}
